/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.submit;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.bioteam.appweb.Config;

import org.ggf.drmaa.JobTemplate;

public abstract class DRMAASubmitter extends LocalBaseCommandSubmitter
{

	public DRMAASubmitter()
	{

	}

	protected String generateScriptFile(UnfinishedJob job, ProgramValueBean bean, String binaryName) throws IOException
	{
		String fileName = job.getWorkdir() + File.separator + SCRIPT_FILE;
		FileWriter writer = new FileWriter(fileName);
		writer.write("#!/bin/sh\n");
		writer.write(Config.envstr);
		writer.write("\n");
		if (binaryName!=null)
		{
			writer.write("APP=`which "+binaryName+"`\n");
		}
		writer.write(job.getCmdline());
		writer.write("\n");
		writer.write("status=$?\n");
		writer.write("\necho $status > " + FINISH_MARK + "\n");
		writer.write("\nexit $status\n");
		writer.close();

		return fileName;
	}

	protected String generatePostScriptFile(UnfinishedJob job, ProgramValueBean bean, String postscript) throws IOException
	{
		String fileName = job.getWorkdir() + File.separator + POST_SCRIPT_FILE;
		FileWriter writer = new FileWriter(fileName);
		writer.write("#!/bin/sh\n");
		writer.write(Config.envstr);
		writer.write("\n");
		writer.write(postscript);
		writer.write("\n");
		writer.write("status=$?\n");
		writer.write("\necho $status > " + FINISH_MARK + "\n");
		writer.write("\nexit $status\n");
		writer.close();

		return fileName;
	}

	protected String submitScript(String filename, UnfinishedJob job, ProgramValueBean bean) throws Exception
	{

		File workdir = new File(job.getWorkdir());
		JobTemplate jt = Config.drmmasession.createJobTemplate();

		jt.setRemoteCommand(filename);
		jt.setWorkingDirectory(workdir.getAbsolutePath());
		String jobname = "n" + workdir.getName();
		if (jobname.length() > 15)
		{
			jobname.substring(0, 15);
		}
		jt.setJobName(jobname);
		jt.setArgs(new ArrayList<String>());
		if (bean.getValue(Config.CATEGORY_KEY) != null)
		{
			jt.setJobCategory(bean.getValue(Config.CATEGORY_KEY).toString());
		}
		jt.setErrorPath(":" + workdir.getAbsolutePath() + File.separator + "job.err");
		jt.setOutputPath(":" + workdir.getAbsolutePath() + File.separator + "job.out");
		if (bean.getValue(Config.NATIVE_KEY) != null)
		{
			jt.setNativeSpecification(bean.getValue(Config.NATIVE_KEY).toString());
		}

		Set<String> emails = new HashSet<String>();
		emails.add(job.getEmail());
		jt.setEmail(emails);

		if (bean.getValue(BULK_JOB) != null && bean.getValue(BULK_JOB).equals("1"))
		{
			int num = Integer.parseInt(bean.getValue(BULK_NUM));
			try
			{
				List ids = Config.drmmasession.runBulkJobs(jt, 1, num, 1);
				return taskIDs2Jobid(ids);
			} finally
			{
				Config.drmmasession.deleteJobTemplate(jt);
			}
		} else
		{
			String jobid;
			try
			{
				jobid = Config.drmmasession.runJob(jt);
			} finally
			{
				Config.drmmasession.deleteJobTemplate(jt);
			}
			return jobid;
		}
	}

	protected String submitPostScript(String filename, UnfinishedJob job, ProgramValueBean bean, String parentJobId) throws Exception
	{

		File workdir = new File(job.getWorkdir());

		JobTemplate jt = Config.drmmasession.createJobTemplate();
		jt.setRemoteCommand(filename);
		jt.setWorkingDirectory(workdir.getAbsolutePath());
		String jobname = "p" + workdir.getName();
		if (jobname.length() > 15)
		{
			jobname.substring(0, 15);
		}
		jt.setJobName(jobname);
		jt.setArgs(new ArrayList<String>());
		if (bean.getValue(Config.CATEGORY_KEY) != null)
		{
			jt.setJobCategory(bean.getValue(Config.CATEGORY_KEY).toString());
		}
		jt.setErrorPath(":" + workdir.getAbsolutePath() + File.separator + "job.err");
		jt.setOutputPath(":" + workdir.getAbsolutePath() + File.separator + "job.out");
		String holdSpec = getHoldNativeSpecification(parentJobId);
		if (bean.getValue(Config.NATIVE_KEY) != null)
		{
			holdSpec += " " + bean.getValue(Config.NATIVE_KEY).toString();

		}
		jt.setNativeSpecification(holdSpec);

		// TODO whether we send email through SGE
		Set<String> emails = new HashSet<String>();
		emails.add(job.getEmail());
		jt.setEmail(emails);

		String jobid;
		try
		{
			jobid = Config.drmmasession.runJob(jt);
		} finally
		{
			Config.drmmasession.deleteJobTemplate(jt);
		}
		return jobid;

	}

	public abstract String taskIDs2Jobid(List ids);

	public abstract String getHoldNativeSpecification(String jobid);

}
